﻿#region Copyright (c) 2011 R. Uittenbosch
/*
* Copyright (C) 2011 R. Uittenbosch
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
* associated documentation files (the "Software"), to deal in the Software without restriction, including 
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 
* following conditions:
* 
* The above copyright notice and this permission notice shall be included in all copies or substantial 
* portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 
* EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#endregion

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Linq;
using System.Reflection;
using System.Collections;
using System.Configuration;
using DatabaseViewer.Interfaces;
using DatabaseViewer.Domain;

namespace DatabaseViewer
{
    public partial class DatabaseViewer : Form
    {
        private DatabaseVisualizer dbv;        
        /// <summary>
        /// The model to show
        /// </summary>
        private IDbModel model;
        /// <summary>
        /// A list of all controls that can be filled by the model
        /// </summary>
        private ControlList containerControls;

        /// <summary>
        /// A list of all controls by typeenum
        /// </summary>
        private Dictionary<ControlType, Control> containerControlsToType;

        /// <summary>
        /// A dictionary of label/textbox controls that represent all filter options
        /// </summary>
        private Dictionary<Control,Control> filtercontrols;

        /// <summary>
        /// The view to start with
        /// </summary>
        private string DefaultView;

        private IVisualizerNodeFactory _factory = new NodeFactory();

        /// <summary>
        /// A list of view elements
        /// </summary>
        private Dictionary<string, ViewConfigElement> Views;

        public DatabaseViewer()
        {
            InitializeComponent();

            // Load views from config
            GetViews();

            containerControlsToType = new Dictionary<ControlType, Control>()
            {
                { ControlType.Container1, splitContainer1.Panel1},
                { ControlType.Container2, splitContainer2.Panel1},
                { ControlType.Container3, splitContainer3.Panel1},
                { ControlType.Container4, splitContainer4.Panel1},
                { ControlType.Tab       , tabControl1}
            };

            containerControls = new ControlList()
            {
                { "Container1", splitContainer1.Panel1},
                { "Container2", splitContainer2.Panel1},
                { "Container3", splitContainer3.Panel1},
                { "Container4", splitContainer4.Panel1},
                { "tabControl", tabControl1}
            };

            // Load different filters
            filtercontrols = new Dictionary<Control,Control>
            {
                {label1, tb1}, {label2, tb2}, {label3, tb3}, {label4, tb4}                
            };
            

            // set first view
            domeinCombo.SelectedIndexChanged -= new EventHandler(domeinCombo_SelectedIndexChanged);
            domeinCombo.SelectedItem = DefaultView;
            LoadModel(domeinCombo.SelectedItem.ToString());
            domeinCombo.SelectedIndexChanged += new EventHandler(domeinCombo_SelectedIndexChanged);
            
        }

        /// <summary>
        /// Get the views from the configuration
        /// </summary>
        private void GetViews()
        {

            ViewConfigurationSection viewSection        = new ViewConfigurationSection();
            System.Configuration.Configuration config   = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            // Add the custom section to the application configuration file.
            if (config.Sections["ViewConfiguration"] == null)
            {
                config.Sections.Add("ViewConfiguration", viewSection);
                viewSection.SectionInformation.ForceSave = true;
                config.Save(ConfigurationSaveMode.Modified);
            }

            // Find and save all
            viewSection = config.GetSection("ViewConfiguration") as ViewConfigurationSection;
            Views = new Dictionary<string, ViewConfigElement>();
            foreach (ViewConfigElement e in viewSection.Views)
            {
                if (e.Type != null)
                    Views.Add(e.Name, e);
            }
            
            // If nothing loaded, create our own
            if (Views.Count == 0)
            {

                foreach (Type t in this.GetType().Assembly.GetTypes())
                {
                    // All classes implementing IDbModel, but not the interface itself
                    if (typeof(IDbModel).IsAssignableFrom(t) && (typeof(IDbModel).ToString() != t.ToString()))
                    {
                        Views.Add(t.Name, new ViewConfigElement(t.Name, t, string.Empty));
                        // Save it for later
                        viewSection.Views.Add(new ViewConfigElement(t.Name, t, string.Empty));
                    }
                }
                // Set the default to the first one we found
                viewSection.Title = "ContractViewer";
                viewSection.Default = Views.First().Key;
                viewSection.SectionInformation.ForceSave = true;
                config.Save(ConfigurationSaveMode.Modified);
            }

            // Order by name
            List<string> names = Views.Keys.ToList<string>();
            names.Sort();

            // Add them to the combo
            foreach (string name in names)
                domeinCombo.Items.Add(name);

            // Get the assembly description (database date)
            AssemblyDescriptionAttribute desc = (AssemblyDescriptionAttribute)
                AssemblyDescriptionAttribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyDescriptionAttribute));

            this.Text = viewSection.Title;
            DefaultView = viewSection.Default;
                  
        }
        
        /// <summary>
        /// Load the model based on the combo
        /// </summary>
        /// <param name="m"></param>
        private void LoadModel(string m)
        {
            // Does it exist?
            if (Views.Keys.Contains(m))
            {
                // Construct to model
                ConstructorInfo c = Views[m].Type.GetConstructor(new Type[] { });
                if (c != null)
                    model = (IDbModel)c.Invoke(null);

                var title = this.Text.Split('-');
                this.Text = title[0].Trim() + " - v" + model.GetType().Assembly.GetName().Version.ToString();
                

                // Put the properties
                model.ConnectionString = Views[m].ConnectionString;

                model.Factory = _factory;

                // disable controls
                foreach (KeyValuePair<Control, Control> pair in filtercontrols)
                {
                    pair.Key.Text = string.Empty;
                    pair.Value.Visible = false;
                }

                //Enable/Show only available controls
                for (int i = 0; i < model.FilterProperties.Count; i++)
                {
                    filtercontrols.ElementAt(i).Key.Text = model.FilterProperties[i];
                    filtercontrols.ElementAt(i).Value.Visible = true;
                }
               
                //// Create the tree based on the filter
                //model.CreateTree(containerControls);

                // Create the tree
                model.CreateTree();
                
                // Delete all controls
                DeleteList();

                // Create a new visualizer
                dbv = new DatabaseVisualizer(this, model.Tree, containerControlsToType);

                // Create the different controls
                dbv.CreateTreeOnForm();

                // Collapse all if nothing found
                if (splitContainer2.Panel1.Controls.Count == 0)
                    splitContainer1.Panel2Collapsed = true;
                else
                    splitContainer1.Panel2Collapsed = false;

                // Geen controls in panel1, dan panel1 collapsed
                splitContainer4.Panel1Collapsed = (splitContainer4.Panel1.Controls.Count == 0);
                // Geen controls in panel1, dan panel1 collapsed
                splitContainer3.Panel1Collapsed = (splitContainer3.Panel1.Controls.Count == 0);
                // Geen controls in panel1, dan panel1 collapsed
                splitContainer2.Panel1Collapsed = (splitContainer2.Panel1.Controls.Count == 0);
                // Geen controls in tabcontrol, dan panel2 collapsed
                splitContainer4.Panel2Collapsed = (tabControl1.TabPages.Count == 0);
               
            }
            else            
                MessageBox.Show("Ongeldige selectie");
            
        }

        private void LoadFromControls(bool expliciet)
        {
            try
            {

                // Get the list of available filters 
                ControlList l = new ControlList();
                foreach (KeyValuePair<Control, Control> pair in filtercontrols)
                {
                    if (!string.IsNullOrEmpty(pair.Key.Text))
                        l.Add(pair.Key.Text, pair.Value);
                }

                Filter f = model.LoadFromControl(l) as Filter;
                if (f.Keys.Count > 0)
                {
                    this.SuspendLayout();
                    model.LoadTree(f);
                    dbv.VisualizeTree();
                    this.Invalidate();
                    this.ResumeLayout();
                }
                else if (expliciet)
                    MessageBox.Show("Geen filter gevonden.");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
       
        private void DeleteList()
        {
            foreach (KeyValuePair<string, Control> c in containerControls)
            { 
                if (c.Value as TabControl != null)
                    (c.Value as TabControl).TabPages.Clear();
                if (c.Value as SplitterPanel != null)
                    (c.Value as SplitterPanel).Controls.Clear();
            }
        }

        private void Clearbt_Click(object sender, EventArgs e)
        {
            tb1.Text = tb4.Text = tb3.Text = tb2.Text = string.Empty;
        }

        private void Loadbt_Click(object sender, EventArgs e)
        {
            LoadFromControls(true);
        }

        private void domeinCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            LoadModel(domeinCombo.SelectedItem.ToString());
            LoadFromControls(false);
        }

        private void tb1_KeyUp(object sender, KeyEventArgs e)
        {
            if ((sender as TextBox).Text != string.Empty)
                if (e.KeyCode == Keys.Enter)
                    LoadFromControls(true);
        }
    }
}
